package com.tsingtao.arch.rule;

import static com.societegenerale.commons.plugin.utils.ArchUtils.importAllClassesInPackage;
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.fields;
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses;
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noFields;
import static com.tngtech.archunit.library.GeneralCodingRules.ACCESS_STANDARD_STREAMS;
import static com.tngtech.archunit.library.GeneralCodingRules.BE_ANNOTATED_WITH_AN_INJECTION_ANNOTATION;
import static com.tngtech.archunit.library.GeneralCodingRules.THROW_GENERIC_EXCEPTIONS;
import static com.tngtech.archunit.library.GeneralCodingRules.USE_JAVA_UTIL_LOGGING;
import static com.tngtech.archunit.library.GeneralCodingRules.USE_JODATIME;

import com.societegenerale.commons.plugin.rules.ArchRuleTest;
import com.societegenerale.commons.plugin.service.ScopePathProvider;
import java.util.Collection;

/**
 * 基础代码规范检查
 */
public class CodingRulesTest implements ArchRuleTest {

  @Override
  public void execute(String packagePath, ScopePathProvider scopePathProvider, Collection<String> excludedPaths) {
    // 不允许使用 printStackTrace() 输出异常信息，使用 Log 形式输出
    noClasses().should(ACCESS_STANDARD_STREAMS)
        .check(importAllClassesInPackage(scopePathProvider.getMainClassesPath(), packagePath, excludedPaths));

    // 不允许直接抛基础异常，比如 RuntimeException
    noClasses().should(THROW_GENERIC_EXCEPTIONS)
        .check(importAllClassesInPackage(scopePathProvider.getMainClassesPath(), packagePath, excludedPaths));

    // 不允许使用 Java util log
    noClasses().should(USE_JAVA_UTIL_LOGGING)
        .check(importAllClassesInPackage(scopePathProvider.getMainClassesPath(), packagePath, excludedPaths));

    // 不用许使用 org.joda.time
    noClasses().should(USE_JODATIME)
        .check(importAllClassesInPackage(scopePathProvider.getMainClassesPath(), packagePath, excludedPaths));

    // 不允许使用注解注入，应该使用构造函数
    noFields().that().areDeclaredInClassesThat().areAnnotatedWith("javax.annotation.Generated")
        .should(BE_ANNOTATED_WITH_AN_INJECTION_ANNOTATION)
        .check(importAllClassesInPackage(scopePathProvider.getMainClassesPath(), packagePath, excludedPaths));

    // 枚举类字段必须申明为 final 类型
    fields().that().areDeclaredInClassesThat().areEnums().should().beFinal()
        .check(importAllClassesInPackage(scopePathProvider.getMainClassesPath(), packagePath, excludedPaths));

  }

}